import {assign, createMachine, send} from "xstate";

const loginProcedure = createMachine({
    id: "LoginProcedure",
    initial: "uninited",
    states: {
        disconnected: {
            entry: ["onDisconnectedEntry", send("FSM_LG_CONNECTING_EVT")],
            on: {
                FSM_LG_CONNECTING_EVT: {
                    target: "connecting",
                },
            },
        },
        connecting: {
            entry: "onConnectingEntry",
            invoke: {
                src: "connect",
                onDone: [
                    {
                        target: "connected",
                    },
                ],
                onError: [
                    {
                        target: "connect_pass_through",
                    },
                ],
            },
        },
        connected: {
            entry: "onConnectedEntry",
            invoke: {
                src: "login",
                onDone: [
                    {
                        target: "logined",
                    },
                ],
                onError: [
                    {
                        target: "login_pass_through",
                        cond: "shouldTryLogin",
                        actions: "onLoginServiceFail",
                    },
                    {
                        target: "loginFail",
                        actions: assign({
                            isTryEnough: false
                        }),
                    }
                ],
            },
        },
        logined: {
            type: "final",
            entry: "onLoginedEntry",
            data: (context: any, event: any) => {
                return {
                    result: true,
                    loginUserInfo: context.loginUserInfo
                }
            }
        },
        login_pass_through: {
            always: [
                {
                    target: "loginFail",
                    actions: assign({
                        isTryEnough: true
                    }),
                    cond: "tryEnough",
                },
                {
                    target: "wait_connecting",
                },
            ],
        },
        loginFail: {
            type: "final",
            entry: "onLoginFailEntry",
            data: (context: any, event: any) => {
                console.log("loginFail", context, event);
                return {
                    result: false,
                    reason: context.isTryEnough ? "登录重试超过次数" : event.data.errMsg
                }
            }
        },
        connect_pass_through: {
            always: [
                {
                    target: "loginFail",
                    cond: "tryEnough",
                    actions: assign({
                        isTryEnough: true
                    }),
                },
                {
                    target: "wait_connecting",
                },
            ],
        },
        wait_connecting: {
            after: {
                "5000": {
                    target: "#LoginProcedure.disconnected",
                    internal: false,
                },
            },
        },
        uninited: {
            entry: ["onLoginUinitedEntry", send("FSM_LG_INIT_EVT")],
            on: {
                FSM_LG_INIT_EVT: {
                    target: "disconnected",
                },
            },
        },
    },
    schema: {
        context: {} as {},
        events: {} as
            | { type: "FSM_LG_CONNECTING_EVT" }
            | { type: "FSM_LG_INIT_EVT" },
    },
    context: {},
    predictableActionArguments: true,
    preserveActionOrder: true,
});


const core_fsm = createMachine({
    id: "Core",
    initial: "uninited",
    states: {
        uninited: {
            entry: "onUinitEntry",
            on: {
                FSM_CORE_INIT_EVT: {
                    target: "inited",
                    actions: "onInitEvt",
                },
            },
        },
        inited: {
            entry: "onInitedEntry",
            on: {
                FSM_CORE_LOGIN_EVT: {
                    target: "logining",
                },
            },
        },
        logining: {
            invoke: {
                src: "LoginProcedure",
                id: "LoginProcedure",
                onDone: [
                    {
                        target: "preparing",
                        cond: "isSucc",
                        actions: "onLoginingSucc",
                    },
                    {
                        target: "inited",
                        actions: "onLoginingFail",
                    },
                ],

                data: {
                    loginParam: (context: any, event: any) => {
                        return event.data;
                    },
                    retryTimes: 0,
                    loginUserInfo: undefined
                }
            },
        },
        preparing: {
            invoke: {
                src: "prepare",
                onDone: [
                    {
                        target: "ready",
                    },
                ],
                onError: [
                    {
                        target: "ready",
                    },
                ],
            },
        },
        ready: {
            exit: "onReadyExit",
            entry: "onReadyEntry",
            on: {
                FSM_CORE_NET_PROBLEM_EVT: {
                    actions: "onDisconnectWhileReady",
                    target: "disconnected",
                },

                FSM_CORE_LOGOUT_EVT: {
                    actions: "onLogoutEvent",
                    target: "inited"
                }
            },
        },
        disconnected: {
            after: {
                100:  {target: "inited", cond: "isLogout"},
                5000: {actions: "onReLoginAction"}
            },

            on: {
                FSM_CORE_LOGIN_EVT: {
                    target: "logining",
                },
            }
        },
    },
    schema: {
        context: {} as {},
        events: {} as
            | { type: "FSM_CORE_INIT_EVT" }
            | { type: "FSM_CORE_NET_PROBLEM_EVT" }
            | { type: "FSM_CORE_LOGIN_EVT" }
            | { type: "FSM_CORE_LOGOUT_EVT"}
    },
    context: {},
    predictableActionArguments: true,
    preserveActionOrder: true,
});


const FSM_CORE_EVENT_CONSTANT = {
    FSM_CORE_INIT_EVT: "FSM_CORE_INIT_EVT",
    FSM_CORE_LOGIN_EVT: "FSM_CORE_LOGIN_EVT",
    FSM_CORE_NET_PROBLEM_EVT: "FSM_CORE_NET_PROBLEM_EVT",
    FSM_CORE_LOGOUT_EVT: "FSM_CORE_LOGOUT_EVT"
};

export {core_fsm, loginProcedure, FSM_CORE_EVENT_CONSTANT};
